package dolf.game;
import dolf.window.*;
import dolf.objects.*;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import java.util.List;


import javax.swing.JOptionPane;
import javax.swing.Timer;
public class Game {
	public static final int PHASE_BUY = -1; // Phase where players can buy
	// weapons
	public static final int PHASE_START_TURN = -2; // Phase showes dialog which
	// player is next
	public static final int PHASE_RUNNING = 2; // Phase where the balls are
	// moving
	public static final int PHASE_DIRECTION = 0; // in this phase aktplayer
	// have to choose the
	// direction of kickoff
	public static final int PHASE_KICKOFF = 1; // in this phase aktplayer sets
	// power of kickoff

	public static final int PHASE_STOP = 3; // in this phase the games is stopped

	private Timer timer;
	private static Game instance;

	private static final int D_TIME = 30;

	private List<Player> players;
	private List<Parcours> parcours;

	private int pacoursToPlay;
	
	private boolean isStarted = false;



	private Game(List<Player> pl, List<Parcours> p){
		players = pl;
		Player.setAktPacour(0);
		pacoursToPlay = p.size();
		for(Player play:players){
			play.setScoreList(p.size());
		}
		instance = this;
		parcours = p;
		System.out.println("Parcours to play:");
		System.out.println("-------------------");
		for (Parcours ps: parcours) {
			System.out.println(ps.getName());
		}
	}
	public static Game getInstance() {
		return instance;
	}

	public static void initGame(List<Player> pl, List<Parcours> p) {
		instance = new Game(pl,p);
	}

	public void startGame(){
		isStarted = true;
		MainWindow.getInstance().draw();
		Level.getInstance().flushLevel();

		//all parcours played?
		if (parcours.isEmpty()) {
			System.out.println("all parcours played, game over");
			javax.swing.JOptionPane.showMessageDialog(MainWindow.getInstance(), finalCalc());

			stopGame();
			
			return;
		} else {
			Level.getInstance().loadParcours(parcours.get(0));
		}

		orderPlayers();

		for(int i = 0; i < players.size(); i++) {
			players.get(i).reset();
			if(Player.getAktPacour()-2 >= 0){
				int money = players.get(i).getMoney()+players.get(i).getScoreList()[Player.getAktPacour()-2][1]*4;
				players.get(i).setMoney(money);
			}
			players.get(i).getBall().setPosition(new Point(Level.getInstance().getStartPos().getX(),Level.getInstance().getStartPos().getY()));
			Level.getInstance().registerObjectOnTop(players.get(i).getBall());
			Level.getInstance().registerPlayer(players.get(i));

		}
		
		if (ConfigurationHandler.getInstance().getProperty("weapons").equals("true")) {
			Level.getInstance().setPhase(PHASE_BUY);
		} else Level.getInstance().setPhase(PHASE_START_TURN);
		
		Level.getInstance().getNextPlayer();
		PlayerDisplay.getInstance().draw();
		BuyWindow.getInstance().reset();
		startTimer();
	}
	public void startTimer(){
		if(timer != null){
			timer.stop();
		}
		timer = new Timer(D_TIME, new ActionListener(){
			public void actionPerformed(ActionEvent e){
				instance.refresh();
			}
		});
		timer.start();
	}

	public void stopTimer() {
		if(timer != null)
			timer.stop();
	}
	
	public void stopGame() {
		stopTimer();
		BuyWindow.getInstance().dispose();
		isStarted = false;
		MainWindow.getInstance().draw();
	}

	public void refresh(){
		if(!Level.getInstance().getPlayers().isEmpty()){
			for(Player play:players){
				play.getBall().clearCollition();
			}
			switch (Level.getInstance().getPhase()){

			case PHASE_BUY:
				if (!BuyWindow.getInstance().isStarted() ) BuyWindow.getInstance().draw(Level.getInstance().getPlayers());
				if (BuyWindow.getInstance().isComplete()) {
					PlayerDisplay.getInstance().draw();
					javax.swing.JOptionPane.showMessageDialog(MainWindow.getInstance(), SystemMessagesHandler.getInstance().getMessages().getString("max_tee")+": " + Level.getInstance().getLimit());	
					Level.getInstance().setPhase(PHASE_START_TURN);
				}

				break;
			case PHASE_START_TURN:
				System.out.println(Level.getInstance().getAktualPlayer().getName());
				Level.getInstance().getAktualPlayer().incHit();

				if(Level.getInstance().getAktualPlayer().getHits()>Level.getInstance().getLimit()){
					javax.swing.JOptionPane.showMessageDialog(MainWindow.getInstance(), Level.getInstance().getAktualPlayer().getName() +" hat das Runden Limit ueberschritten");	
					Level.getInstance().getAktualPlayer().removeHP(Level.getInstance().getAktualPlayer().getHP());
					Level.getInstance().getNextPlayer();
					return;
				}
				ScoreDisplay.getInstance().draw();
				if ( ConfigurationHandler.getInstance().getProperty("show_playername").equals("true")) {
					javax.swing.JOptionPane.showMessageDialog(MainWindow.getInstance(), Level.getInstance().getAktualPlayer().getName());	
				}
				if(Level.getInstance().getAktualPlayer().isDrowned()){
					int antwort = JOptionPane.showConfirmDialog(MainWindow.getInstance(), "Ball ausserhalb des Wasser plazieren?", "Neuplazierung des Balls", JOptionPane.YES_NO_OPTION );
					if (antwort == JOptionPane.NO_OPTION){
						Level.getInstance().getAktualPlayer().getBall().setPosition(Level.getInstance().getStartPos().getCopy());
					}
					Level.getInstance().getAktualPlayer().setDrowned(false);
				}
				if(Level.getInstance().getAktualPlayer() != null && Level.getInstance().getAktualPlayer().getAktWeapon() != null){
					Level.getInstance().getAktualPlayer().getAktWeapon().remove();
				}
				Level.getInstance().setPressed(false);
				Level.getInstance().setPhase(PHASE_DIRECTION);
			case PHASE_DIRECTION:
				if(!Level.getInstance().getAktualPlayer().getBall().isVisible()){
					Level.getInstance().getAktualPlayer().getBall().setVisible(true);
				}
				Level.getInstance().getLoadbar().setVisible(true);
				Level.getInstance().getLoadbar().setLoadstate(0);
				Level.getInstance().getLoadbar().setPosition(new Point(Level.getInstance().getAktualPlayer().getBall().getPosition().getX(), Level.getInstance().getAktualPlayer().getBall().getPosition().getY()));
				Level.getInstance().getLoadbar().setAngle(-Math.atan2(Level.getInstance().getYMouse()-Level.getInstance().getAktualPlayer().getBall().getPosition().getY(), Level.getInstance().getXMouse()-Level.getInstance().getAktualPlayer().getBall().getPosition().getX())*180/Math.PI);
				if(Level.getInstance().mousePressed())
					Level.getInstance().setPhase(PHASE_KICKOFF);
				break;
			case PHASE_KICKOFF:
				if(!Level.getInstance().mousePressed()){
					Level.getInstance().setPhase(PHASE_RUNNING);
					Level.getInstance().getAktualPlayer().getBall().setMotion(new Vector(Math.sin((Level.getInstance().getLoadbar().getAngle()+90)/180*Math.PI)*Level.getInstance().getLoadbar().getLoadstate()/15,Math.cos((Level.getInstance().getLoadbar().getAngle()+90)/180*Math.PI)*Level.getInstance().getLoadbar().getLoadstate()/15));
					Level.getInstance().getLoadbar().setVisible(false);
				} else {
					Level.getInstance().getLoadbar().increaseLoading(3);
				}
				break;
			case PHASE_RUNNING:
				// waffe des aktuellen spielers ausfuehren wenn moeglich
				if(Level.getInstance().getAktualPlayer() != null && Level.getInstance().getAktualPlayer().getAktWeapon() != null){
					Level.getInstance().getAktualPlayer().getAktWeapon().execute();
				}
				/*for(int i = 0; i<Level.getInstance().getPlayers().size(); i++){
						Level.getInstance().getNextPlayer();
						Level.getInstance().getAktualPlayer().getBall().move(Level.getInstance().getObjects());
					}*/
				// moves all objects
				for(int i = 0; i<Level.getInstance().getObjects().size(); i++){
					if(Level.getInstance().getObjects().get(i) instanceof CircleObject && Level.getInstance().getObjects().get(i).isVisible() && Level.getInstance().getObjects().get(i).isMoving()){
						((CircleObject)Level.getInstance().getObjects().get(i)).startMove(Level.getInstance().getObjects());
					}
				}
				// aktueller spieler hat runde ueberlegt und kein ball bewegt sich mehr

				if(Level.getInstance().getAktualPlayer() != null && Level.getInstance().noBallMotion()){
					// waffe des aktuellen spielers entfernen
					if(Level.getInstance().getAktualPlayer().getAktWeapon() != null){
						Level.getInstance().getAktualPlayer().getAktWeapon().remove();
					}
					//					Level.getInstance().getAktualPlayer().setAktWeapon(null);

				}
				// es gibt noch spieler und nichts bewegt sich mehr
				if(Level.getInstance().noMotion()&&!Level.getInstance().getPlayers().isEmpty()){
					Level.getInstance().getNextPlayer();
					Level.getInstance().setPhase(PHASE_START_TURN);
					PlayerDisplay.getInstance().draw();
					ScoreDisplay.getInstance().draw();
				}

			}		
		}		
		Canvas.getInstance().repaint();
		if(Level.getInstance().getPlayers().isEmpty() && Level.getInstance().getPhase() != PHASE_STOP && !Level.getInstance().animationRunning()&&!Level.getInstance().bloodFlow()){
			stopTimer();
			ScoreDisplay.getInstance().draw();
			Level.getInstance().setPhase(PHASE_STOP);
			javax.swing.JOptionPane.showMessageDialog(MainWindow.getInstance(), SystemMessagesHandler.getInstance().getMessages().getObject("round_finished"));
			if (!parcours.isEmpty()) parcours.remove(0);
			startGame();


		}
	}

	public String finalCalc(){
		int[][] res = new int[players.size()][3];
		for(int i = 0; i < players.size(); i++){
			res[i][0] = 0;
			res[i][1] = 0;
			res[i][2] = i;
			for(int j = 0; j < pacoursToPlay; j++){
				res[i][0] += players.get(i).getScoreList()[j][0];
				res[i][1] += players.get(i).getScoreList()[j][1];
			}

		}

		for(int i = 0; i < players.size(); i++){
			for(int j = players.size()-1; j > i; j--){
				if(res[j][0]<=res[j-1][0]){
					boolean change = true;
					if(res[j][0]==res[j-1][0]&&res[j][1]<res[j-1][1]){
						change = false;
					}
					if(change){
						int[] tmp;
						tmp = res[j].clone();
						res[j] = res[j-1];
						res[j-1] = tmp;
					}
				}
			}
		}
		String erg = "<html><table border=0  width=270>";
		for(int i = 0; i<players.size();i++){
			erg = erg+"<tr>";
			erg = erg + "<td align=left>"+(i+1) +". "+"</td>"+
						"<td align=center>"+ players.get(res[i][2]).getName()+"</td>"+
						"<td align=right>"+ res[i][0] +"</td>"+
						"<td align=right>"+res[i][1]+"</td>";
			erg = erg+"</tr>";
		}
		erg = erg+"</table></html>";
		return erg;
	}

	public void orderPlayers(){
		int aktpac = Player.getAktPacour()-2;
		System.out.println("Order");
		if(aktpac < 0){
			List<Player> tmp = new LinkedList<Player>();
			int count = players.size();
			for(int i = 0; i < count; i++){
				int x =(int) (Math.random()*players.size());
				tmp.add(players.get(x));
				players.remove(x);
			}
			players = tmp;
			System.out.println("Random");
		} else {
			for(int i = 0; i < players.size(); i++){
				for(int j = players.size()-1; j > i; j--){
					Player pl1 = players.get(j);
					Player pl2 = players.get(j-1);
					if(pl1.getScoreList()[aktpac][1] >= pl2.getScoreList()[aktpac][1]){
						if(pl1.getScoreList()[aktpac][1] != pl2.getScoreList()[aktpac][1] || Math.random() >0.5){
							Player temp = pl2; 
							players.set(j-1, pl1);
							players.set(j, temp);
						}
					}
				}
			}
		}

		for(int i = 0; i < players.size(); i++){
			System.out.print(players.get(i).getName() +" ");
			if(aktpac >= 0)
				System.out.println(players.get(i).getScoreList()[aktpac][1]);
		}
	}
	
	public boolean isStarted() {
		return isStarted;
	}
	public List<Player> getPlayerList() {
		return players;
	}
}
